module dungeonish.main;

version(build) pragma(export_version, Windowed);

import std.stdio;
import std.string;
import std.conv;
import std.path;

import derelict.util.exception;
import derelict.sdl.sdl;

import nade.color;


int main(char[][] args)
{
	if(args.length < 5)
	{
		writefln("Usage: TileSplitter <filename> <width> <height> <dest>");
		return 0;
	}

	try
	{
		DerelictSDL.load("Modules\\SDL.dll");


		if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
		{
			writefln("Unable to initialize SDL: %s", SDL_GetError());
			SDL_Quit();
			return 1;
		}

		version(Windowed)
			auto screen = SDL_SetVideoMode(1024, 768, 32, SDL_OPENGL);
		else
			auto screen = SDL_SetVideoMode(1024, 768, 32, SDL_OPENGL | SDL_FULLSCREEN);
		if(screen is null)
		{
			writefln("Unable to set 1024x768 video: %s", SDL_GetError());
			SDL_Quit();
			return 1;
		}


		auto src = SDL_LoadBMP(toStringz(args[1]));
		uint tw = to!(uint)(args[2]);
		uint th = to!(uint)(args[3]);
		string dest = to!(string)(args[4]) ~ getName(getBaseName(to!(string)(args[1])));

		int cw = src.w/tw;
		int ch = src.h/th;
		for(int y = 0;  y < ch;  ++y)
		{
			for(int x = 0;  x < cw;  ++x)
			{
				auto dst = SDL_CreateRGBSurface(SDL_SWSURFACE, tw, th, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000);

				for(int py = 0;  py < tw;  ++py)
				{
					for(int px = 0;  px < tw;  ++px)
					{
						putPixelRaw(dst, px, py, getPixelRaw(src, px + x*tw, py + y*th));
					}
				}

				// SDL_SaveBMP(dst, toStringz(format("%s%02dx%02d.bmp", dest, x, y)));
				SDL_SaveBMP(dst, toStringz(format("%s%03d.bmp", dest, x + y*cw)));
			}
		}
	}
	catch(Exception e)
	{
		e.print;
	}

	SDL_Quit();

	return 0;
}


uint getPixelRaw(SDL_Surface* surface, int x, int y)
{
	const bpp = surface.format.BytesPerPixel;
	ubyte* p = cast(ubyte*)surface.pixels + y*surface.pitch + x*bpp;

	switch(bpp)
	{
		case 1: return *p;
		case 2: return *cast(ushort*)p;
		case 3:
		{
			if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
				return (p[0] << 16) | (p[1] << 8) | p[2];
			else
				return p[0] | (p[1] << 8) | (p[2] << 16);
		}
		case 4: return *cast(uint*)p;

		default: assert(false);
	}

	return 0;
}

Color getPixel(SDL_Surface* surface, int x, int y)
{
	ubyte r, g, b;
	SDL_GetRGB(getPixelRaw(surface, x, y), surface.format, &r, &g, &b);

	// if(r == 0xFF  &&  g == 0x00  &&  b == 0xFF)
		// return Color(r/255.0, g/255.0, b/255.0, 1.0);

	return Color(r/255.0, g/255.0, b/255.0, 1.0);
}


void putPixelRaw(SDL_Surface *surface, int x, int y, uint color)
{
    const bpp = surface.format.BytesPerPixel;
    ubyte* p = cast(ubyte*)surface.pixels + y*surface.pitch + x*bpp;

    switch(bpp)
	{
	    case 1: *p = cast(ubyte)color; break;
	    case 2: *cast(ushort*)p = cast(ubyte)color; break;
	    case 3:
		{
	        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
	            p[0] = cast(ubyte)(color&0xFF), p[1] = cast(ubyte)((color >> 8)&0xFF), p[2] = cast(ubyte)((color >> 16)&0xFF);
			else
	            p[0] = cast(ubyte)((color >> 16)&0xFF), p[1] = cast(ubyte)((color >> 8)&0xFF), p[2] = cast(ubyte)(color&0xFF);
	        break;
		}
	    case 4: *cast(uint*)p = color; break;

		default: assert(false);
    }
}

void putPixel(SDL_Surface *surface, int x, int y, Color color)
{
	putPixelRaw(
		surface,
		x, y,
		SDL_MapRGBA(
			surface.format,
			cast(ubyte)(color.r*255.0),
			cast(ubyte)(color.g*255.0),
			cast(ubyte)(color.b*255.0),
			cast(ubyte)(color.a*255.0)
			)
		);
}
